/*
 * Copyright (c) 2009, Jan Pastor. All Rights Reserved.
 */

package sk.jp.jitag.pok1.gui;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import sk.jp.commons.ui.ExceptionDialog;
import sk.jp.commons.utils.DateUtils;
import sk.jp.commons.utils.LogMsg;
import sk.jp.commons.utils.LogUtil;
import sk.jp.imageio.jpeg.JpegImage;
import sk.jp.imageio.jpeg.JpegImageIo;
import sk.jp.imageio.jpeg.JpegImageIoImpl;
import sk.jp.imageio.jpeg.metadata.Tag;
import sk.jp.jitag.pok1.Pok1Msg;
import sk.jp.jitag.util.Property;

public class Pok1MainWindow extends JFrame implements ActionListener {

    private static final Logger log = LoggerFactory.getLogger(Pok1MainWindow.class);

    private JpegImageIo imageIo;

    enum ActionCode {
        open,
        exit,
        rotateLeft,
        rotateRight,
        zoom,
        save,
        openDir;
    }

    private JLabel imagePlace;
    private JpegImage jpegImage;

    //----------------------------------------------------------------------

    public Pok1MainWindow() throws HeadlessException {
        super(Pok1Msg.mainWndTitle.value());
        init();
        setupContent();
    }

    //----------------------------------------------------------------------

    public void open(){
        pack();
        setSize(Property.defaultMainWndWidth.intValue(),
                Property.defaultMainWndHeight.intValue());
        Toolkit t = Toolkit.getDefaultToolkit();
        Dimension sd = t.getScreenSize();
        Dimension dd = getSize();
        setLocation((sd.width - dd.width) / 2, (sd.height - dd.height) / 2);
        setVisible(true);
    }

    //----------------------------------------------------------------------

    private void init(){
        JpegImageIoImpl jpegImageIo = new JpegImageIoImpl();
        jpegImageIo.setLazyEnabled(true);
        imageIo = jpegImageIo;

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void setupContent(){
        setLayout(new BorderLayout());
        add(new JLabel(Pok1Msg.aboutApp.value()), BorderLayout.NORTH);

        imagePlace = new JLabel(" ");
        imagePlace.setBackground(Color.WHITE);
        add(imagePlace, BorderLayout.CENTER);

        JPanel btnPane = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        add(btnPane, BorderLayout.SOUTH);

        btnPane.add(createButton(Pok1Msg.openDirectory, ActionCode.openDir));
        btnPane.add(createButton(Pok1Msg.openFile, ActionCode.open));
        btnPane.add(createButton(Pok1Msg.rotateLeft, ActionCode.rotateLeft));
        btnPane.add(createButton(Pok1Msg.rotateRight, ActionCode.rotateRight));
        btnPane.add(createButton(Pok1Msg.zoom, ActionCode.zoom));
        btnPane.add(createButton(Pok1Msg.save, ActionCode.save));
        btnPane.add(createButton(Pok1Msg.exit, ActionCode.exit));
    }

    private JButton createButton(Pok1Msg label, ActionCode actionCode){
        JButton button = new JButton(label.value());
        button.addActionListener(this);
        button.setActionCommand(actionCode.name());
        return button;
    }

    public void actionPerformed(ActionEvent e) {
        try {
            processAction(e.getActionCommand());
        } catch (Throwable ex) {
            log.error("Unexpected exception", ex);
            try {
//                showErrorMessage(ex.getMessage());
                ExceptionDialog.show(this, ex);
            } catch (Throwable e1) {
                log.error("Unexpected exception during show error message dialog", e1);
            }
        }
    }

    private void showErrorMessage(String message){
        JOptionPane.showMessageDialog(this, message, "error",
                                      JOptionPane.ERROR_MESSAGE);
    }

    private void processAction(String command){
        log.debug(LogMsg.inp("command", command));
        if(ActionCode.open.name().equals(command)){
            actionOpen();
        }else if(ActionCode.openDir.name().equals(command)){
            actionOpenDir();
        }else if(ActionCode.exit.name().equals(command)){
            exitApp();
        }else if(ActionCode.rotateLeft.name().equals(command)){
            rotateLeft();
        }else if(ActionCode.rotateRight.name().equals(command)){
            rotateRight();
        }else if(ActionCode.zoom.name().equals(command)){
            zoomImage();
        }else if(ActionCode.save.name().equals(command)){
            saveImage();
        }else{
            log.warn(LogMsg.toString("Unknown action command", "command", command));
        }
    }

    private void actionOpenDir(){
        JFileChooser fc = new JFileChooser();
        fc.setFileFilter(new FileFilter() {
            @Override
            public boolean accept(File f) {
                return f.isDirectory();
            }
            @Override
            public String getDescription() {
                return "Directory";
            }
        });
        fc.setCurrentDirectory(new File("e:/_temp_prenos/jitagtestdir"));
        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int result = fc.showOpenDialog(this);

        if(result != JFileChooser.APPROVE_OPTION){
            return;
        }
        File directory = fc.getSelectedFile();

        Set<File> directories = new LinkedHashSet<File>();
        directories.add(directory);
        java.io.FileFilter filter = new java.io.FileFilter() {
            public boolean accept(File pathname) {
                return pathname.isDirectory();
            }
        };
        File[] files = directory.listFiles(filter); //TODO Dokoncit!!! recursion
        for (int i = 0; i < files.length; i++) {
            File subdir = files[i];
            directories.add(subdir);
        }

        List<JpegImage> jpegImageList = imageIo.loadImages(directories);
        imagePlace.setText("Loaded " + jpegImageList.size() + " files");

//        for (JpegImage image : jpegImageList) {
//            ImageIcon imageIcon = new ImageIcon(image.getThumbnail(new Dimension(200, 200)));
//            imagePlace.setIcon(imageIcon);
//            image.free();
//            if(log.isTraceEnabled()){
//                log.trace(LogUtil.getMemoryStateLogMessage());
//            }
//        }
    }

    private void actionOpen(){
        if(log.isTraceEnabled()){
            log.trace(LogUtil.getMemoryStateLogMessage());
        }

        JFileChooser fc = new JFileChooser();
        fc.setFileFilter(new FileFilter() {
            @Override
            public boolean accept(File f) {
                return f.isDirectory() || f.getName().toLowerCase().endsWith(".jpg");
            }
            @Override
            public String getDescription() {
                return "JPEG images";
            }
        });
        fc.setCurrentDirectory(new File("e:/_temp_prenos/jitagtestdir"));
        int result = fc.showOpenDialog(this);

        if(result != JFileChooser.APPROVE_OPTION){
            return;
        }
        File file = fc.getSelectedFile();

        jpegImage = imageIo.loadImage(file);

        ImageIcon imageIcon = new ImageIcon(jpegImage.getThumbnail(new Dimension(200, 200)));
        imagePlace.setIcon(imageIcon);

        jpegImage.free();
        if(log.isTraceEnabled()){
            log.trace(LogUtil.getMemoryStateLogMessage());
        }
    }

    private void exitApp(){
        setVisible(false);
        //noinspection CallToSystemExit
        System.exit(0);
    }

    private void rotateLeft(){
        if(jpegImage == null){
            showErrorMessage("No image is open.");
//            return;
        }
        jpegImage.rotateLeft();
        imageIo.saveImage(jpegImage);
        ImageIcon imageIcon = new ImageIcon(jpegImage.getThumbnail(new Dimension(200, 200)));
        imagePlace.setIcon(imageIcon);
        jpegImage.free();
        if(log.isTraceEnabled()){
            log.trace(LogUtil.getMemoryStateLogMessage());
        }
    }

    private void rotateRight(){
        if(jpegImage == null){
            showErrorMessage("No image is open.");
            return;
        }
        jpegImage.rotateRight();
        ImageIcon imageIcon = new ImageIcon(jpegImage.getThumbnail(new Dimension(200, 200)));
        imagePlace.setIcon(imageIcon);

        imageIo.saveImage(jpegImage);
        jpegImage.free();
        if(log.isTraceEnabled()){
            log.trace(LogUtil.getMemoryStateLogMessage());
        }
    }

    private void zoomImage(){
        if(jpegImage == null){
            showErrorMessage("No image is open.");
            return;
        }
        BufferedImage zoomedImage = jpegImage.getBufferedImage(new Dimension(400, 400));
        ImageIcon imageIcon = new ImageIcon(zoomedImage);
        imagePlace.setIcon(imageIcon);

        jpegImage.free();
        if(log.isTraceEnabled()){
            log.trace(LogUtil.getMemoryStateLogMessage());
        }
    }

    private void saveImage(){
        if(jpegImage == null){
            showErrorMessage("No image is open.");
            return;
        }

        String nt = DateUtils.date2String(DateUtils.SORTABLE_DATETIME);
        jpegImage.getTags().add(new Tag(nt));
        int nr = (jpegImage.getRating().getValue() + 1) % 4;
        jpegImage.getRating().setValue(nr);

        imageIo.saveImage(jpegImage);
//        imageIo.saveImageMetadata(jpegImage);
    }

}
